home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The X-Philes (2nd Revision)
/
The X-Philes Number 1 (1995).iso
/
xphiles
/
hp48_2
/
vsrc.tar
/
voyager7_src
/
index.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-27
|
16KB
|
873 lines
/*
// Abstract:
// INDEX---Comment File Indexing
//
// The Comment File Indexing module handles storing and fetching of
// address and code comments.
//
// Author:
// Derek S. Nickel
//
// Creation date:
// 12 November 1990
//
// History:
// V01-001 Derek S. Nickel 12-NOV-1990
// Original.
//
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include "index.h"
#include "memory.h"
#include "modes.h"
#include "tree.h"
typedef struct {
bin5_t key;
long value;
} filenode_t;
#define MAX_LINE 256
static char cbuf[MAX_LINE]; /* for returned comments */
#define BRAVE 0
/***********************************************************************
Messages.
***********************************************************************/
#define vgr__makeidx \
"%%VOYAGER-I-MAKEIDX, making index for %s\n"
#define vgr__notyetava \
"%%VOYAGER-I-NOTYETAVA, operation is not yet available\n"
#define vgr__merging \
"%%VOYAGER-I-MERGING, merging %s into %s\n"
#define vgr__merged \
"%%VOYAGER-I-MERGED, %ld out of %ld comments from %s merged into %s\n"
#define vgr__openin \
"%%VOYAGER-E-OPENIN, error opening %s as input\n"
#define vgr__readidx \
"%%VOYAGER-I-READIDX, reading index for %s\n"
#define vgr__sorted \
"%%VOYAGER-I-SORTTXT, %ld comments written to %s\n"
#define vgr__sorting \
"%%VOYAGER-I-SORTTXT, writing %s (sorted)\n"
#define vgr__writeidx \
"%%VOYAGER-I-WRITEIDX, writing index for %s\n"
#define rms$_fnf \
"-RMS-E-FNF, file not found\n"
#if VGR_TRACE & 0x00000001
#define TRACE(t1,t2,t3,t4) { \\
printf("Trace: "); \\
printf(t1,t2,t3,t4); \\
printf("\n"); }
#else
#define TRACE(t1,t2,t3,t4)
#endif
/***********************************************************************
file_open
***********************************************************************/
static FILE *file_open(char *name, char *type)
{
FILE *ans;
TRACE("opening %s, mode %s", name, type, 0);
ans = fopen(name, type);
if (ans == NULL) {
printf(vgr__openin, name);
exit(-1);
}
return ans;
}
/***********************************************************************
compare_node
***********************************************************************/
static int compare_node(bin5_t *data, node_t **node, char *junk)
{
int result = 0;
TRACE("comparing %05lX to %05lX", *data, (*node)->key, 0);
if (*data < (*node)->key)
result = -1;
else if (*data > (*node)->key)
result = 1;
return result;
}
/***********************************************************************
allocate_node
***********************************************************************/
static int allocate_node(bin5_t *key, node_t **node, char *junk)
{
*node = malloc(sizeof(node_t));
TRACE("allocated node for %05lX at %p", *key, *node, 0);
if (*node == NULL) {
printf("error allocating node for %05lX\n", *key);
exit(-1);
}
(*node)->key = *key;
(*node)->value = 0;
(*node)->deleted = 0;
return 1;
}
/***********************************************************************
deallocate_node
***********************************************************************/
static int deallocate_node(node_t *node, char *junk)
{
TRACE("deallocating node for %05lX at %p", node->key, *node, 0);
free(node);
return 1;
}
/***********************************************************************
write_one_index
***********************************************************************/
typedef struct _wrtidx_t wrtidx_t;
struct _wrtidx_t {
FILE *f;
};
static int write_one_index(node_t *node, wrtidx_t *db)
{
filenode_t fnode;
TRACE("Node: %p, Key: %05lX, Value: %ld\n",
node, node->key, node->value );
/*
// If this node has not been flagged as deleted...
*/
if (!node->deleted) {
/*
// Copy data (index info) to file node and write to
// index file.
*/
fnode.key = node->key;
fnode.value = node->value;
fwrite(&fnode, sizeof(filenode_t), 1, db->f);
}
return 1;
}
/***********************************************************************
GetTextLine
***********************************************************************/
char *GetTextLine(text_file_t *tf, bin5_t key)
{
char *cbufp;
node_t *node;
cond_value stat;
/*
// Get the information for this symbol.
*/
stat = lookup_tree(
&tf->root,
&key,
compare_node,
&node );
/*
// If it was found...
*/
if (stat & 1) {
if (!node->deleted) {
fseek(tf->f, node->value, SEEK_SET);
fgets(cbuf, sizeof(cbuf), tf->f);
cbuf[strlen(cbuf)-1] = '\0';
cbufp = cbuf+6;
} else {
cbuf[0] = '\0';
cbufp = cbuf;
}
} else {
cbuf[0] = '\0';
cbufp = cbuf;
}
return cbufp;
}
/***********************************************************************
DelTextLine
***********************************************************************/
void DelTextLine(text_file_t *tf, bin5_t key)
{
node_t *node;
cond_value stat;
char c;
stat = lookup_tree(
&tf->root,
&key,
compare_node,
&node );
if (stat & 1) {
if (!node->deleted) {
fseek(tf->f, node->value, SEEK_SET);
fputc('-', tf->f);
node->deleted = 1;
tf->changes++;
tf->count--;
}
}
}
/***********************************************************************
AddTextLine
***********************************************************************/
void AddTextLine(text_file_t *tf, bin5_t key, char *cmt)
{
char *buf[240];
long p;
node_t *node;
cond_value stat;
char c;
/*
// Create new entry (or get existing entry).
*/
stat = insert_tree(
&tf->root,
&key,
0,
compare_node,
allocate_node,
&node,
0 );
/*
// Mark old comment as deleted.
*/
if (stat == lib$_keyalrins) {
if (!node->deleted) {
fseek(tf->f, node->value, SEEK_SET);
fputc('-', tf->f);
node->deleted = 1;
tf->changes++;
tf->count--;
}
}
/*
// Add the comment to the file and update the node.
*/
fseek(tf->f, 0, SEEK_END);
node->value = ftell(tf->f);
fprintf(tf->f, "%05lX %s\n", key, cmt);
node->deleted = 0;
tf->changes++;
tf->count++;
}
/***********************************************************************
merge_text_line
***********************************************************************/
void merge_text_line(text_file_t *tf, bin5_t key, char *cmt)
{
char *buf[240];
long p;
node_t *node;
cond_value sys_status;
/*
// Create new entry (or get existing entry).
*/
sys_status = insert_tree(
&tf->root,
&key,
0,
compare_node,
allocate_node,
&node,
0 );
/*
// Add new comment only if no existing (undelted) entry.
*/
if ((sys_status != lib$_keyalrins) || (node->deleted)) {
/*
// Add the comment to the file and update the node.
*/
fseek(tf->f, 0, SEEK_END);
node->value = ftell(tf->f);
fprintf(tf->f, "%05lX %s\n", key, cmt);
node->deleted = 0;
tf->changes++;
tf->count++;
}
}
/***********************************************************************
read_text_index
***********************************************************************/
static void read_text_index(text_file_t *tf)
{
FILE *f;
node_t *node;
filenode_t fnode;
cond_value stat;
if (modes.info) printf(vgr__readidx, tf->fnmap);
/*
// Open the index.
*/
f = file_open(tf->fninx, "rb");
tf->count = 0;
/*
// Get the first entry from the index file.
*/
fread(&fnode, sizeof(filenode_t), 1, f);
/*
// While not end-of-file...
*/
while (!feof(f)) {
/*
// Create new entry.
*/
stat = insert_tree(
&tf->root,
&fnode.key,
0,
compare_node,
allocate_node,
&node,
0 );
/*
// Update the node.
*/
node->value = fnode.value;
node->deleted = 0;
/*
// Count this entry.
*/
tf->count++;
/*
// Get the next entry from the index file.
*/
fread(&fnode, sizeof(filenode_t), 1, f);
}
/*
// Close the index file and clear changes counter.
*/
fclose(f);
tf->changes = 0;
}
/***********************************************************************
write_text_index
***********************************************************************/
static void write_text_index(text_file_t *tf)
{
wrtidx_t db;
cond_value sys_status;
if (modes.info) printf(vgr__writeidx, tf->fnmap);
/*
// Open the index file.
*/
db.f = file_open(tf->fninx, "wb");
/*
// Write out the index, skipping deleted entries.
*/
sys_status = traverse_tree(
&tf->root,
write_one_index,
&db );
/*
// Close the index file.
*/
fclose(db.f);
/*
// Index file is now up-to-date.
*/
tf->changes = 0;
}
/***********************************************************************
make_text_index
***********************************************************************/
static void make_text_index(text_file_t *tf)
{
char buf[240];
long wh;
node_t *node;
bin5_t key;
cond_value stat;
if (modes.info) printf(vgr__makeidx, tf->fnmap);
/*
// Reset changes counter. If any comments are found, this will
// be increamented, causing the index to be updated upon exit.
*/
tf->changes = 0;
tf->count = 0;
/*
// Reset to beginning of file.
*/
fseek(tf->f, 0L, SEEK_SET);
while (!feof(tf->f)) {
/*
// Get the text and position of the next comment.
*/
wh = ftell(tf->f);
if (!fgets(buf, sizeof(buf), tf->f)) break;
buf[5] = '\0';
/*
// If this comment has not been flagged as deleted...
*/
if (*buf != '-') {
/*
// Count this comment.
*/
tf->changes++;
tf->count++;
/*
// Convert address from hex string to integer.
*/
key = str2adr(buf, 0);
/*
// Create a new index entry.
*/
stat = insert_tree(
&tf->root,
&key,
0,
compare_node,
allocate_node,
&node,
0 );
/*
// Update the node.
*/
node->value = wh;
node->deleted = 0;
}
}
}
/***********************************************************************
destroy_text_index
***********************************************************************/
static void destroy_text_index(text_file_t *tf)
{
cond_value stat;
TRACE("destroying index %s", tf->fninx, 0, 0);
/*
// Get rid of all the nodes in the index.
*/
stat = post_order_traversal(
&tf->root,
deallocate_node,
NULL );
tf->root = NULL;
}
/***********************************************************************
open_text_file
***********************************************************************/
void open_text_file(text_file_t *tf, char *filename, char *code)
{
/*
// Open/create the comment file.
*/
strcpy(tf->fnmap, filename);
strcat(tf->fnmap, ".");
strcat(tf->fnmap, code);
if (access(tf->fnmap,0)) {
FILE *f = file_open(tf->fnmap, "wt");
fclose(f);
}
tf->f = file_open(tf->fnmap, "r+t");
/*
// Read/make the comment file's index.
*/
strcpy(tf->fninx, tf->fnmap);
strcat(tf->fninx, "X");
/*
// Does the index exist?
*/
if (access(tf->fninx,0)) {
/*
// No index.
*/
make_text_index(tf);
} else {
struct stat map_stat;
struct stat inx_stat;
/*
// Compare the modification times between the
// comment file and its index.
*/
stat(tf->fnmap, &map_stat);
stat(tf->fninx, &inx_stat);
if (inx_stat.st_mtime < map_stat.st_mtime) {
/*
// Index is out-of-date (text file has been
// modified.
*/
make_text_index(tf);
} else {
/*
// Index is up-to-date.
*/
read_text_index(tf);
}
}
}
/***********************************************************************
close_text_file
***********************************************************************/
void close_text_file(text_file_t *tf)
{
fclose(tf->f);
if (tf->changes) write_text_index(tf);
destroy_text_index(tf);
}
/***********************************************************************
open_memory_file
***********************************************************************/
void open_memory_file(FILE **xfile, char *module)
{
char fname[_MAX_PATH];
strcpy(fname, module);
strcat(fname, ".MEM");
*xfile = file_open(fname, "r+t");
}
/***********************************************************************
close_memory_file
***********************************************************************/
void close_memory_file(FILE *xfile)
{
fclose(xfile);
}
/***********************************************************************
write_one_line
***********************************************************************/
typedef struct _sortdata_t sortdata_t;
struct _sortdata_t {
FILE *f;
text_file_t *tf;
long count;
};
static int write_one_line(node_t *node, sortdata_t *db)
{
char *cbufp;
TRACE("(sort) Node: %p, Key: %05lX, Value: %ld\n",
node, node->key, node->value );
if (!node->deleted) {
fseek(db->tf->f, node->value, SEEK_SET);
fgets(cbuf, sizeof(cbuf), db->tf->f);
cbuf[strlen(cbuf)-1] = '\0';
cbufp = cbuf+6;
fprintf(db->f, "%05lX %s\n", node->key, cbufp);
db->count++;
};
return 1;
}
/***********************************************************************
sort_text_file
***********************************************************************/
void sort_text_file(text_file_t *tf, char *filename, char *code,
char *tmpnam, int *idx)
{
cond_value stat;
char newfile[_MAX_PATH];
char oldfile[_MAX_PATH];
char t[4];
sortdata_t db;
if (modes.info) printf(vgr__sorting, tf->fnmap);
/*
// Build intermediate file names.
*/
sprintf(t, "%03hX", *idx);
(*idx)++;
strcpy(newfile, tmpnam);
strcat(newfile, ".");
strcat(newfile, t);
#if !BRAVE
sprintf(t, "%03hX", *idx);
(*idx)++;
strcpy(oldfile, tmpnam);
strcat(oldfile, ".");
strcat(oldfile, t);
#endif
/*
// Create the new comment file with a temporary name.
*/
db.f = file_open(newfile, "wt");
/*
// Store pointer to the text file.
*/
db.tf = tf;
/*
// Clear comments count.
*/
db.count = 0;
/*
// Write out the comments in sorted order, skipping deleted
// comments.
*/
stat = traverse_tree(
&tf->root,
write_one_line,
&db );
/*
// Close all files.
*/
fclose(db.f);
fclose(tf->f);
/*
// Remove (or rename) the old comment file.
*/
#if BRAVE
remove(tf->fnmap);
#else
rename(tf->fnmap, oldfile);
#endif
/*
// Rename the new comment file.
*/
rename(newfile, tf->fnmap);
/*
// Display sort statistics.
*/
printf(vgr__sorted, db.count, tf->fnmap);
/*
// Open the new comment file.
*/
tf->f = file_open(tf->fnmap, "r+t");
/*
// Recreate the index.
*/
destroy_text_index(tf);
make_text_index(tf);
}
/***********************************************************************
merge_text_file
***********************************************************************/
void merge_text_file(text_file_t *tf, char *new_module, char *code)
{
FILE *ifile;
char ibuf[MAX_LINE];
char *cmt;
long merges;
long attempts;
bin5_t key;
char *nl_pos;
if (modes.info) printf(vgr__merging, new_module, tf->fnmap);
/*
// Save current count (for merged count).
*/
merges = tf->changes;
attempts = 0;
/*
// Open the input file.
*/
ifile = file_open(new_module, "rt");
/*
// Read from the input and merge in new comments.
*/
while (!feof(ifile)) {
if (fgets(ibuf,MAX_LINE,ifile)) {
key = strtoul(ibuf,&cmt,16);
if (*cmt) {
/* skip leading blank or separator */
cmt++;
while (*cmt == ' ')
cmt++;
nl_pos = strrchr(cmt,'\n');
if (nl_pos) *nl_pos = '\0';
attempts++;
merge_text_line(tf, key, cmt);
}
}
}
/*
// Close the input file.
*/
fclose(ifile);
/*
// Calculate number of comments merged in.
*/
merges = tf->changes - merges;
/*
// Display merge statistics.
*/
printf(vgr__merged, merges, attempts, new_module, tf->fnmap);
}